
if (true) {
    var foo = " zce";
}
console.log(foo); // 打印：zec

if (true) {
    let foo1 = " zce";
}
// console.log(foo1); // 打印：foo1 is not defined


for (var i = 0; i < 3; i++) {
    for (var i = 0; i < 3; i++) {
        console.log(i); // 012
    }
}

for (let i = 0; i < 3; i++) {
    for (let i = 0; i < 3; i++) {
        console.log(i); // 012012012
    }
}


var elements = [{}, {}, {}];
// 正常写法：会出现打印的i固定为循环的累加值
// for (var i = 0; i < elements.length; i++) {
//     elements[i].onclick = function () {
//         console.log('elements:', i);;
//     }
// }

// elements[0].onclick();
// elements[1].onclick();
// elements[2].onclick();

// 解决方案1 ： 通过闭包
// for (var i = 0; i < elements.length; i++) {
//     elements[i].onclick = (function (i) {
//         return function () {
//             console.log('elements:', i);;
//         }
//     })(i)
// }

// elements[0].onclick();
// elements[1].onclick();
// elements[2].onclick();

// 解决方案二： 通过let
for (let i = 0; i < elements.length; i++) {
    elements[i].onclick = function () {
        console.log('elements:', i);;
    }
}

elements[0].onclick();
elements[1].onclick();
elements[2].onclick();


/**
 * ES6 新增了let命令，用来声明局部变量。它的用法类似于var，但是所声明的变量，只在let命令所在的代码块内有效，而且有暂时性死区的约束。
 *
 * ES6 明确规定，如果区块中存在let和const命令，这个区块对这些命令声明的变量，从一开始就形成了封闭作用域。凡是在声明之前就使 用这些变量，就会报错。
    总之，在代码块内，使用let命令声明变量之前，该变量都是不可用的。这在语法上，称为“暂时性死区”（temporal dead zone，简称 TDZ）。

    let非常适合用于 for循环内部的块级作用域。JS中的for循环体比较特殊，每次执行都是一个全新的独立的块作用域，用let声明的变量传入到 for循环体的作用域后，不会发生改变，不受外界的影响。

    let不允许在相同作用域内，重复声明同一个变量。否则报错。
 */